﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace RSHTreelReset
{
    public sealed class StringEncryption : IDisposable
    {
        private readonly SymmetricAlgorithm myCryptoService;

        public StringEncryption(StringEncryption.StringEncryptionMethod method)
        {
            if (method != StringEncryption.StringEncryptionMethod.DES)
                return;
            this.myCryptoService = (SymmetricAlgorithm)DES.Create();
        }

        public StringEncryption(SymmetricAlgorithm serviceProvider)
        {
            this.myCryptoService = serviceProvider;
        }

        public void Dispose()
        {
            if (this.myCryptoService == null)
                return;
            this.myCryptoService.Dispose();
        }

        private byte[] GetLegalKey(string key)
        {
            if (this.myCryptoService.LegalKeySizes.Length > 0)
            {
                KeySizes keySizes = this.myCryptoService.LegalKeySizes[0];
                if (key.Length * 8 > keySizes.MaxSize)
                {
                    while (key.Length * 8 > keySizes.MaxSize)
                        key = key.Remove(key.Length - 1, 1);
                }
                else
                {
                    while (key.Length * 8 < keySizes.MinSize)
                        key = key + (object)' ';
                }
            }
            return Encoding.UTF8.GetBytes(key);
        }

        public string Encrypt(string source, string key)
        {
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(source);
                MemoryStream memoryStream = new MemoryStream();
                byte[] legalKey = this.GetLegalKey(key);
                this.myCryptoService.Key = legalKey;
                this.myCryptoService.IV = legalKey;
                ICryptoTransform encryptor = this.myCryptoService.CreateEncryptor();
                CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write);
                cryptoStream.Write(bytes, 0, bytes.Length);
                cryptoStream.FlushFinalBlock();
                byte[] buffer = memoryStream.GetBuffer();
                int index = buffer.Length - 1;
                while (index >= 0 && (int)buffer[index] == 0)
                    --index;
                return Convert.ToBase64String(buffer, 0, index + 1);
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }

        public string Decrypt(string source, string key)
        {
            if (source.Length == 0)
                return string.Empty;
            try
            {
                byte[] buffer = Convert.FromBase64String(source);
                if (buffer.Length % 8 != 0)
                {
                    byte[] numArray = new byte[8 * (buffer.Length / 8) + 8];
                    Array.Copy((Array)buffer, (Array)numArray, buffer.Length);
                    buffer = numArray;
                }
                MemoryStream memoryStream = new MemoryStream(buffer, 0, buffer.Length);
                byte[] legalKey = this.GetLegalKey(key);
                this.myCryptoService.Key = legalKey;
                this.myCryptoService.IV = legalKey;
                ICryptoTransform decryptor = this.myCryptoService.CreateDecryptor();
                return new StreamReader((Stream)new CryptoStream((Stream)memoryStream, decryptor, CryptoStreamMode.Read)).ReadToEnd();
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }

        public enum StringEncryptionMethod
        {
            DES,
            RC2,
            Rijndael,
        }
    }
}
